<template>
	<view class="drop-down" :class="{'setDropdownBottom':maskVisibility}">
		<!-- 顶部插槽 -->
		<view class="header">
			<slot name="header"></slot>
		</view>
		<view class="main">
			<!-- 顶部菜单 -->
			<view class="nav">
				<block v-for="(item,index) in menu" :key="index">
					<view class="first-menu" :class="{'on':current==index}" @click="togglePage(index)">
						<text class="txt" :class="{'checked-color': checkedColor(item)}">
							<slot name="title" :title="item">
								{{showTitle(item)}}
							</slot>
						</text>
						<text class="name"></text>
					</view>
				</block>
			</view>
			<!-- 遮罩层 -->
			<view class="mask" v-if="overlay" :class="{'show':isShowMask,'hide':maskVisibility!=true}"
				@click="hideMenu(true, 'mask')"></view>
			<view class="sub-menu-container" :style="{display: maskVisibility ? 'block' : 'none'}">
				<view class="sub-menu-list">
					<block v-for="(item,index) in menuData" :key="index">
						<view class="sub-menu-class"
							:class="{'show':current==index,'hide':!pageState[index], 'show-shadow':shadow}">
							<block v-if="(item.type=='hierarchy'||item.type=='hierarchy-column'||item.type=='single-hierarchy')&& item[childName].length>0">
								<drop-item-menu-vue3 :item="item" :currentIndex="index" :firstScrollInto="firstScrollInto"
									:secondScrollInto="secondScrollInto" :thirdScrollInto="thirdScrollInto"
									:childName="childName" :fileds="fileds" ref="itemMenu" style="width: 100%;"
									@close="emitColse" @change="changeMenuTitle($event, index)">
								</drop-item-menu-vue3>
							</block>
							<!-- 多选筛选 -->
							<block v-if="item.type=='filter'">
								<view class="filter">
									<drop-item-vue3 :item="item" :childName="childName" :fileds="fileds" ref="dropItem" @change="changeMenuTitle($event, index)">
										<template v-slot:filterItem="{item}">
											<slot name="filter" :item="item"></slot>
										</template>
									</drop-item-vue3>
								</view>
							</block>

							<!-- 单选筛选 -->
							<block v-if="item.type=='radio'">
								<view class="filter">
									<drop-item-vue3 :item="item" type="radio" :childName="childName" :fileds="fileds" ref="dropItem" @change="changeMenuTitle($event, index)">
									</drop-item-vue3>
								</view>
							</block>

							<view class="btn-box" v-if="!autoStow||item.type=='filter'||item.type=='radio'||item.type=='priceRadio'">
								<view class="reset" @click="resetFilter()">重置</view>
								<view class="submit" @click="confirmFilter()">确定</view>
							</view>
						</view>
					</block>
				</view>
			</view>
		</view>
	</view>
</template>
<script>
import { ref, unref, toRaw, nextTick, watch, computed, getCurrentInstance } from 'vue'
import { deepClone } from '../../lib/util.js'
export default {
	name: 'DropDownVue3',
	/**
	 * @property {Array}						filterData  		渲染的数组（默认 []）
	 * @property {String}						childName  			子菜单字段（默认 submenu）
	 * @property {String}						fileds  			显示字段	（默认 name）
	 * @property {Boolean}		  				isChild				返回值是否包含子菜单 （默认 false，可选 true）
	 * @property {Boolean}		  				autoStow			菜单类型为 hierarchy 或 hierarchy-column 时选择完成之后是否自动收起菜单并返回选中值，默认 true，选择所有子																		  菜单后再收起，如果有多级时，希望选择一级或二级菜单时就收起，需要设置为 false，点击确定收起
	 * @property {Boolean}						resetStow  			重置是否收起，默认 false，可选 true
	 * @property {Boolean}						overlay  			是否显示遮罩，默认 true，可选 false
	 * @property {Boolean}						closeOnClickOverlay 点击遮罩是否收起菜单，默认 true，可选 false
	 * @property {Boolean}						shadow  			是否显示菜单下阴影，默认 true，可选 false
	 * @property {Function() <array> {}}		confirm  			返回所有选中的对象
	 * */
	props: {
		filterData: {
			value: Array,
			default: []
		},
		childName: {
			type: String,
			default: 'submenu'
		},
		fileds: {
			type: String,
			default: "name"
		},
		isChild: {
			type: Boolean,
			default: false
		},
		autoStow: {
			type: Boolean,
			default: true
		},
		resetStow: {
			type: Boolean,
			default: false
		},
		overlay: {
			type: Boolean,
			default: true
		},
		closeOnClickOverlay: {
			type: Boolean,
			default: true
		},
		shadow: {
			type: Boolean,
			default: true
		}
	},
	emits: ['reset', 'confirm'],
	setup: (props, {emit}) => {
		const menuData = ref([])
		const menu = ref([]) //顶部菜单数据
		const current = ref(-1) //菜单页面显示/隐藏动画控制
		const pageState = ref([]) //页面的状态
		const isShowMask = ref(false) //遮罩层显示/隐藏动画控制
		const maskVisibility = ref(false) //遮罩层显示/隐藏状态
		
		//滚动区域定位
		const firstScrollInto = ref(0)
		const secondScrollInto = ref(0)
		const thirdScrollInto = ref(0)
		
		// 多列选择
		const columns = ref([])
		
		// 单选/多选
		const filter = ref([])
		const radio = ref([])
		
		const result = ref([])
		
		const instance = getCurrentInstance()
		
		function checkedColor(item) {
			return item.checkedName && item.checkedName.length
		}
		function showTitle(item) {
			const it = unref(item)
			return (it.checkedName && it.checkedName.length) ? it.checkedName.join('/') : it[props
				.fileds]
		}
		function init() {
			let tmpMenu = [];
			for (let i = 0; i < unref(menuData).length; i++) {
				let tmpitem = toRaw(unref(menuData)[i]);
				tmpMenu.push({
					[props.fileds]: tmpitem[props.fileds] || (tmpitem.type == "filter" ? "筛选" : tmpitem[props.childName] ? tmpitem[props.childName][0][props.fileds] : '筛选'),
					type: tmpitem.type,
					checkedName: []
				});
				pageState.value.push(false);
			}
			// 提取 nav 
			menu.value = tmpMenu;
		}

		// 为每一项添加标识
		function addIdentity(data, level = 0) {
			if (!data || !data.length) return
			data.forEach(item => {
				item.drop_item_identity = level
				if (item[props.childName] && item[props.childName].length) {
					addIdentity(item[props.childName], level + 1)
				}
			})
		}

		//写入结果，合并
		function confirmFilter() {
			result.value.length = 0
			getListValue()
			getFilterOrRadioValue()
			formatResult()
			hideMenu(false)
		}
		//重置结果和ui，筛选
		function resetFilter(page_index) {
			const itemMenu = instance.proxy.$refs.itemMenu
			const dropItem = instance.proxy.$refs.dropItem
			if (!(!itemMenu || !itemMenu.length)) {
				itemMenu.forEach(component => {
					component.current = -1
					component.sec_current = -1
					component.sec2_current = -1
					component.selectArr = []
				})
			}
			if (!dropItem || !dropItem.length) return
			dropItem.forEach(component => {
				component.selectFilterArr = []
				component.selectRadioArr = []
				component.filter = []
				component.radio = []
				component.showNumberRange = false
				const newItem = component.newItem
				resetCompValue(newItem[props.childName])	
			})
			
			// 重置tabs菜单
			unref(menu).map(item => {
				item.checkedName = []
			})
			// 修改组件
			emit('reset')
		}
		function resetCompValue(submenu) {
			submenu && submenu.map(it => {
				if (it.$component === 'numberRange') {
					it.maxValue && (it.maxValue = '')
					it.minValue && (it.minValue = '')
				} else if (it[props.childName] && it[props.childName].length) {
					resetCompValue(it[props.childName])
				}
				
			})
		}
		// 取类型为 filter 或 radio 的选中值
		function getFilterOrRadioValue() {
			const dropItem = instance.proxy.$refs.dropItem
			if (!dropItem || !dropItem.length) return
			dropItem.forEach(component => {
				result.value.push(...(component.selectFilterArr || []), ...(component.selectRadioArr || []))
			})
		}

		// 取类型为 列表筛选 的选中值
		function getListValue() {
			const itemMenu = instance.proxy.$refs.itemMenu
			if (!itemMenu || !itemMenu.length) return
			itemMenu.forEach(component => {
				result.value.push(...(component.selectArr || []))
			})
		}

		//菜单开关
		function togglePage(index) {
			if (index == unref(current)) {
				hideMenu(true);
			} else {
				showMenu(index)
			}
		}


		// 隐藏菜单
		function hideMenu(hideReturn = false, type) {
			if (!props.closeOnClickOverlay && type === 'mask') return
			hideMenuLayer(true);
			hideMaskLayer();
			current.value = -1;
			if (hideReturn) confirmFilter()
		}

		// 显示菜单
		function showMenu(index) {
			if (unref(current) > -1) {
				hideMenuLayer(false);
			}
			showMenuLayer(index);
			showMaskLayer();
		}
		//隐藏遮罩层
		function hideMaskLayer() {
			isShowMask.value = false;
			setTimeout(() => {
				maskVisibility.value = false;
			}, 200);
		}

		//显示遮罩层
		function showMaskLayer() {
			maskVisibility.value = true;
			nextTick(() => {
				setTimeout(() => {
					isShowMask.value = true;
				}, 0)
			})
		}

		//隐藏菜单页
		function hideMenuLayer(isAnimation) {
			let tmpIndex = unref(current);
			if (isAnimation) {
				setTimeout(() => {
					pageState.value.splice(tmpIndex, 1, false);
				}, 200);
			} else {
				pageState.value.splice(tmpIndex, 1, false)
			}
			firstScrollInto.value = null;
			secondScrollInto.value = null;
		}

		//显示菜单页
		function showMenuLayer(index) {
			pageState.value.splice(index, 1, true);
			nextTick(() => {
				setTimeout(() => {
					current.value = index;
				}, 0)
			})
		}

		// 处理结果并返回
		function formatResult() {
			const res = deepClone(unref(result))
			const data = removeCustomAttributes(res)
			emit('confirm', data)
		}

		function emitColse(flag) {
			if (props.autoStow && flag) {
				confirmFilter()
			}
		}

		// 点击改变头部标题
		function changeMenuTitle(data, index) {
			if (!data || !data.length) {
				return unref(menu)[index].checkedName = []
			}
			
			const item = menu.value[index]
			if (item.type === 'filter' || item.type === 'radio' || item.type === 'single-hierarchy') {
				item.checkedName = [item[props.fileds]]
			} else if (item.type === 'hierarchy' || item.type === 'hierarchy-column') {
				item.checkedName = []
				data.forEach((el) => {
					item.checkedName.push(el[props.fileds])
				})
			}		
		}
		// 移除组件自定义属性
		function removeCustomAttributes(data) {
			if (!data || !data.length) return []
			data.forEach(el => {
				delete el.drop_item_key;
				delete el.pKey;
				delete el.drop_item_identity;
				delete el.parent_type;
				!props.isChild && delete el[props.childName];
				if (props.isChild && el[props.childName]) {
					removeCustomAttributes(el[props.childName])
				}
			})
			return data
		}
		watch(
		() => props.filterData, 
		(newVal) => {
			menuData.value.length = 0
			nextTick(() => {
				menuData.value = deepClone(newVal);
				init();
				addIdentity(unref(menuData).map(item => toRaw(item)), 0)
			})	
		}, {
			immediate: true,
			deep: true
		})
		init();
		addIdentity(unref(menuData).map(item => toRaw(item)), 0)
		
		return {
			maskVisibility,
			menu,
			isShowMask,
			hideMenu,
			menuData,
			pageState,
			firstScrollInto,
			secondScrollInto,
			thirdScrollInto,
			emitColse,
			changeMenuTitle,
			resetFilter,
			confirmFilter,
			current,
			togglePage,
			showTitle,
			checkedColor
		}
	}
}
</script>
<style lang="scss" scoped>
view {
	display: flex;
	flex-wrap: nowrap;
}

.drop-down {
	flex-shrink: 0;
	width: 100%;
	// position: fixed;
	// position: sticky;
	z-index: 997;
	flex-wrap: nowrap;
	display: flex;
	flex-direction: row;

	flex-direction: column;

	.deg0 {
		transform: rotateZ(0deg);
	}

	.deg180 {
		transform: rotateZ(180deg);
	}

	&.setDropdownBottom {
		// height: 345px;
		bottom: 0;
	}

}

.header {
	z-index: 12;
	background-color: #fff;
}

.main {
	position: relative;
	.nav {
		width: 100%;
		height: 88rpx;
		border-bottom: solid 2rpx #eee;
		z-index: 12;
		background-color: #ffffff;
		flex-direction: row;
	
		.first-menu {
			width: 100%;
			font-size: 26rpx;
			color: #757575;
			flex-direction: row;
			align-items: center;
			justify-content: center;
			transition: color .2s linear;
	
			&.on {
				color: $uni-color-primary;
	
				.iconfont {
					color: $uni-color-primary;
				}
	
				.name::before {
					background-color: $uni-color-primary;
					transform: translate(150%, -50%) rotateZ(40deg);
				}
	
				.name::after {
					background-color: $uni-color-primary;
					transform: translate(210%, -50%) rotateZ(-40deg);
				}
			}
	
			.name {
				position: relative;
				height: 40rpx;
				text-align: center;
				text-overflow: clip;
	
				// overflow: hidden;
				&::after,
				&::before {
					content: "";
					position: absolute;
					right: 0;
					top: 50%;
					width: 10rpx;
					height: 5rpx;
					background-color: #757575;
					transition: transform 0.3s linear;
				}
	
				&::before {
					transform: translate(150%, -50%) rotateZ(-40deg);
				}
	
				&::after {
					transform: translate(210%, -50%) rotateZ(40deg);
				}
			}
	
			.txt {
				display: inline-block;
				max-width: 80rpx;
				overflow: hidden;
				white-space: nowrap;
			}
	
			.checked-color {
				color: $uni-color-primary;
			}
		}
	}
	
	.show-shadow {
		box-shadow: 0 4rpx 20rpx rgba(#ccc, 1);
	}
	.sub-menu-container {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 808rpx;
		overflow: hidden;
		.sub-menu-list {
			position: relative;
			width: 100%;
			height: 100%;
			.sub-menu-class {
				background-color: #ffffff;	
				align-items: center;
				flex-direction: column;
				position: absolute;
				width: 100%;
				height: 100%;
				left: 0;
				transform: translate3d(0, - 100%, 0);
				z-index: 11;
				overflow: hidden;
				transition: transform .15s linear;
				&.hide {
					display: none;
				}

				&.show {
					transform: translate3d(0, calc(88rpx + 1rpx), 0);
				}

				.btn-box {
					flex-shrink: 0;
					width: 698rpx;
					height: 122rpx;
					flex-direction: row !important;
					align-items: center;
					justify-content: space-between;
					>view {
						width: 320rpx;
						height: 80rpx;
						border-radius: 80rpx;
						border: solid 1rpx $uni-color-primary;
						align-items: center;
						justify-content: center;
					}

					.reset {
						color: $uni-color-primary;
					}

					.submit {
						color: #fff;
						background-color: $uni-color-primary;
					}
				}
			}
		}
	}
	
	.filter {
		width: 100%;
		height: 600rpx;
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		align-items: center;
	
		.menu-box {
			width: 698rpx;
			height: calc(690rpx - 120rpx);
			flex-shrink: 1;
	
			.box {
				width: 100%;
				padding-top: 32rpx;
				flex-direction: column;
			}
		}
	}
	
	.mask {
		z-index: 10;
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background-color: rgba(0, 0, 0, 0);
		transition: background-color .15s linear;
	
		&.show {
			background-color: rgba(0, 0, 0, 0.5);
		}
	
		&.hide {
			display: none;
		}
	}
}

</style>
